#!/usr/bin/env python
# -*- coding: utf-8 -*-

from base64 import b64encode,b64decode


#######################################################################

class   Packet(object) :
    REQUEST  = 'REQUEST'
    RESPONSE = 'RESPONSE'

    INSERT = 'INSERT'
    ERASE  = 'ERASE'
    LOOKUP = 'LOOKUP'

    def __init__(self) :
        self._type = None
        self.action = None
        self.key = None
        self.timeout = 0
        self.data = None
        self.status = 0
        # __init__()

    def isRequest(self) :
        return self._type == self.REQUEST
        # isRequest()
    def isResponse(self) :
        return self._type == self.RESPONSE
        # isResponse()
    def setRequest(self) :
        self._type = self.REQUEST
        # setRequest()
    def setResponse(self) :
        self._type = self.RESPONSE
        # setResponse()

    def isInsertAction(self) :
        return  self.action == self.INSERT
        # isInsert()
    def isEraseAction(self) :
        return  self.action == self.ERASE
        # isErase()
    def isLookupAction(self) :
        return  self.action == self.LOOKUP
        # isLookup()
    def setInsertAction(self) :
        self.action = self.INSERT
        # setInsert()
    def setEraseAction(self) :
        self.action = self.ERASE
        # setErase()
    def setLookupAction(self) :
        self.action = self.LOOKUP
        # setLookup()

    # class Packet

FIELD_SEPARATOR = '\t'
KV_SEPARATOR = ':'

def encodeRequest(packet) :
    if not packet.isRequest() :
        raise TypeError, 'REQUEST packet wanted.'

    fields = []
    fields.append(KV_SEPARATOR.join(('key',packet.key)))
    if packet.isInsertAction() :
        fields.append(KV_SEPARATOR.join(('action','INSERT')))
        fields.append(KV_SEPARATOR.join(('expiration', '%d' % packet.timeout)))
        fields.append(KV_SEPARATOR.join(('data',packet.data)))
    elif packet.isEraseAction() :
        fields.append(KV_SEPARATOR.join(('action','ERASE')))
    elif packet.isLookupAction() :
        fields.append(KV_SEPARATOR.join(('action','LOOKUP')))

    record = FIELD_SEPARATOR.join(fields)
    return b64encode(record)
    # encodeResponse()

def decodeRequest(request) :
    record = b64decode(request)
    fields = record.strip().split(FIELD_SEPARATOR)

    packet = Packet()
    packet.setRequest()
    for f in fields :
        k,v = f.strip().split(KV_SEPARATOR)
        if 'action' == k :
            if 'INSERT' == v : packet.setInsertAction()
            elif 'ERASE' == v : packet.setEraseAction()
            elif 'LOOKUP' == v : packet.setLookupAction()
        elif 'key' == k :
            packet.key = v
        elif 'expiration' == k :
            packet.timeout = int(v)
        elif 'data' == k :
            packet.data = v

    return packet
    # decodeRequest()

def encodeResponse(packet) :
    if not packet.isResponse() :
        raise TypeError, 'RESPONSE packet wanted.'

    fields = []
    fields.append(KV_SEPARATOR.join(('key',packet.key)))
    fields.append(KV_SEPARATOR.join(('status',str(packet.status))))
    if packet.isInsertAction() :
        fields.append(KV_SEPARATOR.join(('action','INSERT')))
        fields.append(KV_SEPARATOR.join(('expiration', '%d' % packet.timeout)))
    elif packet.isEraseAction() :
        fields.append(KV_SEPARATOR.join(('action','ERASE')))
    elif packet.isLookupAction() :
        fields.append(KV_SEPARATOR.join(('action','LOOKUP')))
        if packet.data : fields.append(KV_SEPARATOR.join(('data',packet.data)))

    record = FIELD_SEPARATOR.join(fields)
    return b64encode(record)
    # encodeResponse()

def decodeResponse(response) :
    record = b64decode(response)
    fields = record.strip().split(FIELD_SEPARATOR)

    packet = Packet()
    packet.setResponse()
    for f in fields :
        k,v = f.strip().split(KV_SEPARATOR)
        if 'action' == k :
            if 'INSERT' == v : packet.setInsertAction()
            elif 'ERASE' == v : packet.setEraseAction()
            elif 'LOOKUP' == v : packet.setLookupAction()
        elif 'key' == k :
            packet.key = v
        elif 'expiration' == k :
            packet.timeout = int(v)
        elif 'data' == k :
            packet.data = v
        elif 'status' == k :
            packet.status = int(v)

    return packet
    # decodeRequest()

